/**
 * Oct 10, 2013 10:36:38 AM
 * com.kratonsolution.belian.security.impl.dao
 * AccessDao.java
 */
package com.kratonsolution.belian.security.impl.dao;

import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.springframework.stereotype.Component;

import com.google.common.base.Strings;
import com.kratonsolution.belian.common.util.Numbers;
import com.kratonsolution.belian.common.util.Paging;
import com.kratonsolution.belian.security.api.dao.AccessDao;
import com.kratonsolution.belian.security.api.dao.SecurityDao;
import com.kratonsolution.belian.security.api.dm.Access;

/**
 * @author Agung Dodi Perdana
 * @email agung.dodi.perdana@gmail.com
 * @Version Sinch 0.0.1
 */
@Component
public class AccessDaoImpl extends SecurityDao implements AccessDao
{
    public Access store(Access model)
    {
        getSession().persist(model);
        return model;
    }

    public Access load(String id)
    {
        return (Access)getSession().get(Access.class, id);
    }

    public Access update(Access model)
    {
        getSession().merge(model);
        return model;
    }

    public Access remove(Access model)
    {
        getSession().delete(model);
        return model;
    }

    public List<Access> loads()
    {
        Query query = getSession().createQuery("FROM Access");
        query.setReadOnly(true);
        query.setCacheable(true);
        
        return query.list();
    }

    public List<Access> loads(Map<String, Object> param)
    {
        if(param == null || param.isEmpty())
            return loads();
        
        StringBuilder builder = new StringBuilder();
        builder.append("FROM Access access WHERE access.id IS NOT NULL ");
        
        if(param.containsKey("moduleId"))
            builder.append("AND access.moduleId = :moduleId ");
        
        if(param.containsKey("moduleCode"))
            builder.append("AND access.moduleCode = :moduleCode ");
        
        if(param.containsKey("moduleName"))
            builder.append("AND access.moduleName like :moduleName ");
        
        if(param.containsKey("roleId"))
            builder.append("AND access.roleId = :roleId ");
        
        if(param.containsKey("roleName"))
            builder.append("AND access.roleName like :roleName ");
        
        builder.append(" ORDER BY access.moduleId,access.roleId ASC ");
        
        Query query = getSession().createQuery(builder.toString());
        query.setCacheable(true);
        query.setFirstResult(Paging.getStart(param.get("start")));
        query.setMaxResults(Paging.getRowPerPage(param.get("max")));
        
        if(param.containsKey("moduleId"))
            query.setParameter("moduleId",param.get("moduleId"));
        
        if(param.containsKey("moduleCode"))
            query.setParameter("moduleCode",param.get("moduleCode"));
        
        if(param.containsKey("moduleName"))
            query.setParameter("moduleName",param.get("moduleName"));
        
        if(param.containsKey("roleId"))
            query.setParameter("roleId",param.get("roleId"));
        
        if(param.containsKey("roleName"))
            query.setParameter("roleName",param.get("roleName"));
        
        return query.list();
    }

    public long count()
    {
        Query query = getSession().createQuery("SELECT COUNT(access) FROM Access");
        query.setReadOnly(true);
        query.setCacheable(true);
        
        return Numbers.toLong(query.uniqueResult());
    }

    public long count(Map<String, Object> param)
    {
        if(param == null || param.isEmpty())
            return count();
        
        StringBuilder builder = new StringBuilder();
        builder.append("SELECT COUNT(access) FROM Access access WHERE access.id IS NOT NULL ");
        
        if(param.containsKey("moduleId"))
            builder.append("AND access.moduleId = :moduleId ");
        
        if(param.containsKey("moduleCode"))
            builder.append("AND access.moduleCode = :moduleCode ");
        
        if(param.containsKey("moduleName"))
            builder.append("AND access.moduleName like :moduleName ");
        
        if(param.containsKey("roleId"))
            builder.append("AND access.roleId = :roleId ");
        
        if(param.containsKey("roleName"))
            builder.append("AND access.roleName like :roleName ");
        
        builder.append(" ORDER BY access.moduleId,access.roleId ASC ");
        
        Query query = getSession().createQuery(builder.toString());
        query.setCacheable(true);
        
        if(param.containsKey("moduleId"))
            query.setParameter("moduleId",param.get("moduleId"));
        
        if(param.containsKey("moduleCode"))
            query.setParameter("moduleCode",param.get("moduleCode"));
        
        if(param.containsKey("moduleName"))
            query.setParameter("moduleName",param.get("moduleName"));
        
        if(param.containsKey("roleId"))
            query.setParameter("roleId",param.get("roleId"));
        
        if(param.containsKey("roleName"))
            query.setParameter("roleName",param.get("roleName"));
        
        return Numbers.toLong(query.uniqueResult());
    }

    public Access get(String roleId, String serviceCode)
    {        
        if(Strings.isNullOrEmpty(roleId) || Strings.isNullOrEmpty(serviceCode))
            return null;
        
        StringBuilder builder = new StringBuilder();
        builder.append("FROM Access access WHERE access.moduleCode = :moduleCode AND access.roleId = :roleId ");
        
        Query query = getSession().createQuery(builder.toString());
        query.setCacheable(true);
        query.setParameter("roleId",roleId);
        query.setParameter("moduleCode",serviceCode);
        
        List<Access> list = query.list();
        if(!list.isEmpty())
            return list.get(0);
            
        return null;
    }

    public List<Access> loads(String roleId)
    {
        Query query = getSession().createQuery("FROM Access access WHERE access.roleId =:role ");
        query.setCacheable(true);
        query.setReadOnly(true);
        query.setParameter("role",roleId);
        
        return query.list();
    }

}
